package com.manage.platform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.manage.platform.constants.JwtConstant;
import com.manage.platform.constants.RedisPrefixConstants;
import com.manage.platform.context.UserContext;
import com.manage.platform.dto.UserDto;
import com.manage.platform.dto.UserLoginDto;
import com.manage.platform.dto.UserUpdatePasswordDto;
import com.manage.platform.excel.UserExcel;
import com.manage.platform.dto.query.UserPageQuery;
import com.manage.platform.entity.UserEntity;
import com.manage.platform.exception.CommonException;
import com.manage.platform.exception.EmError;
import com.manage.platform.mapper.UserMapper;
import com.manage.platform.po.UserPo;
import com.manage.platform.properties.DefaultProperties;
import com.manage.platform.utils.JwtTokenUtil;
import com.manage.platform.utils.RPage;
import com.manage.platform.utils.RedisUtil;
import com.manage.platform.vo.*;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * YWD
 * 2025/9/18
 */
@AllArgsConstructor
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> {

    private final RedisUtil redisUtil;
    private final DefaultProperties defaultProperties;
    private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    private final OrganizeMemberServiceImpl organizeMemberServiceImpl;
    private final RoleMenuServiceImpl roleMenuServiceImpl;

    /**
     * 登录
     *
     * @param dto
     * @return
     */
    public String login(UserLoginDto dto) {
        if (StringUtils.isBlank(dto.getUserName())) throw new CommonException(EmError.USER_ADD_IS_NULL);
        // 用户信息
        UserPo userPo = this.baseMapper.getUserInfo(null, dto.getUserName());
        if (ObjectUtil.isEmpty(userPo)) throw new CommonException(EmError.AUTH_USER_IS_NULL);
        // 校验密码
        if (!passwordEncoder.matches(dto.getPassword(), userPo.getPassword()))
            throw new CommonException(EmError.AUTH_PASSWORD_ERROR);
        // 构建返回对象
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(userPo, userVo);
        // 生成JwtToken
        long expireTime = dto.getRememberMe() ? JwtConstant.EXPIRATION_REMEMBER : JwtConstant.EXPIRATION;
        String token = JwtTokenUtil.createToken(userVo.getId().toString(), expireTime * 1000L);
        userVo.setToken(token);
        // 存入Redis，如果缓存时间更长就使用缓存时间
        Long redisExpireTime = redisUtil.getExpire(RedisPrefixConstants.MANAGE_PLATFORM_USER_INFO + userVo.getId());
        if (Objects.nonNull(redisExpireTime) && redisExpireTime > expireTime) {
            expireTime = redisExpireTime;
        }
        //缓存用户信息
        UserContext.setUser(userVo);
        redisUtil.setObject(RedisPrefixConstants.MANAGE_PLATFORM_USER_INFO + userVo.getId(), userVo, expireTime);
        return userVo.getToken();
    }


    public UserDetailsVo getUserInfo() {
        UserVo userVo = UserContext.getUser();
        UserDetailsVo userDetailsVo = new UserDetailsVo();
        userDetailsVo.setUserVo(userVo);
        // 用户权限信息
        List<MenuTreeVo> menuList = roleMenuServiceImpl.getMenuByRoleId(userVo.getRoleId());
        if (CollectionUtil.isNotEmpty(menuList)) {
            userDetailsVo.setMenuTreeVoList(menuList);
        }
        return userDetailsVo;
    }

    public Boolean resetPassword(Long id) {
        try {
            //密码加密
            String encode = passwordEncoder.encode(defaultProperties.getPassword());
            LambdaUpdateWrapper<UserEntity> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper
                    .eq(UserEntity::getId, id)
                    .set(UserEntity::getPassword, encode);
            //清除缓存
            UserContext.clearUser();
            redisUtil.deleteKey(RedisPrefixConstants.MANAGE_PLATFORM_USER_INFO + id);
            return update(updateWrapper);
        } catch (Exception e) {
            throw new CommonException(EmError.USER_UPDATE_PASSWORD_ERROR);
        }
    }

    public Boolean updatePassword(UserUpdatePasswordDto dto) {
        try {
            //用户信息
            UserEntity entity = this.getById(dto.getId());
            //旧校验密码
            if (!passwordEncoder.matches(dto.getPassword(), entity.getPassword()))
                throw new CommonException(EmError.AUTH_OLD_PASSWORD_ERROR);
            //新密码加密
            String encode = passwordEncoder.encode(dto.getNewPassword());
            LambdaUpdateWrapper<UserEntity> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper
                    .eq(UserEntity::getId, dto.getId())
                    .set(UserEntity::getPassword, encode);
            //清除缓存
            UserContext.clearUser();
            redisUtil.deleteKey(RedisPrefixConstants.MANAGE_PLATFORM_USER_INFO + dto.getId());
            return update(updateWrapper);
        } catch (CommonException e) {
            throw new CommonException(EmError.USER_UPDATE_PASSWORD_ERROR);
        }
    }

    public RPage<List<UserVo>> getUserPage(UserPageQuery query) {
        Page<Object> page = PageHelper.startPage(query.getPage(), query.getLimit());
        List<UserVo> list = this.baseMapper.getUserPage(query);
        return RPage.ok(list, query.getPage(), query.getLimit(), page.getTotal());
    }

    public UserVo getUserDetails(Long id) {
        return this.baseMapper.getUserDetails(id);
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean saveUser(UserDto dto) {
        // 账号是否存在
        UserPo userInfo = this.baseMapper.getUserInfo(null, dto.getUserName());
        if (ObjectUtil.isNotEmpty(userInfo)) throw new CommonException(EmError.USER_ADD_IS_EXIST);
        // 手机号是否被使用
        String phone = this.baseMapper.getUserByPhone(null, dto.getPhone());
        if (StringUtils.isNotBlank(phone)) throw new CommonException(EmError.USER_ADD_PHONE_EXISTED);
        // 密码加密
        if (StringUtils.isBlank(dto.getPassword())) {
            dto.setPassword(defaultProperties.getPassword());
        }
        String encode = passwordEncoder.encode(dto.getPassword());
        dto.setPassword(encode);
        this.baseMapper.saveUser(dto);
        // 用户关联组织(部门)
        if (CollectionUtil.isNotEmpty(dto.getDepartmentId())) {
            organizeMemberServiceImpl.saveMember(dto.getId(), dto.getDepartmentId());
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean updateUser(UserDto dto) {
        // 账号是否存在
        UserPo userInfo = this.baseMapper.getUserInfo(dto.getId(), dto.getUserName());
        if (ObjectUtil.isNotEmpty(userInfo)) throw new CommonException(EmError.USER_ADD_IS_EXIST);
        //手机号是否被使用
        String phone = this.baseMapper.getUserByPhone(dto.getId(), dto.getPhone());
        if (StringUtils.isNotBlank(phone)) throw new CommonException(EmError.USER_ADD_PHONE_EXISTED);
        //密码加密
        if (StringUtils.isBlank(dto.getPassword())) {
            dto.setPassword(defaultProperties.getPassword());
        }
        String encode = passwordEncoder.encode(dto.getPassword());
        dto.setPassword(encode);
        // 先删除再关联组织(部门)
        organizeMemberServiceImpl.removeByMemberId(dto.getId());
        if (CollectionUtil.isNotEmpty(dto.getDepartmentId())) {
            organizeMemberServiceImpl.saveMember(dto.getId(), dto.getDepartmentId());
        }
        return updateById(BeanUtil.copyProperties(dto, UserEntity.class));
    }

    public Boolean deleteUser(Long id) {
        if (id == 1) {
            throw new CommonException(EmError.USER_DELETE_AUTH_ERROR);
        }
        //删除关联
        organizeMemberServiceImpl.removeByMemberId(id);
        //清除缓存
        UserContext.clearUser();
        redisUtil.deleteKey(RedisPrefixConstants.MANAGE_PLATFORM_USER_INFO + id);
        return removeById(id);
    }

    public Boolean getByRoleId(Long roleId) {
        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(UserEntity::getRoleId, roleId)
                .eq(UserEntity::getIsDeleted, 0);
        List<UserEntity> list = this.baseMapper.selectList(queryWrapper);
        if (CollectionUtil.isEmpty(list)) {
            return false;
        }
        return true;
    }

    public Boolean getByDepartmentId(Long departmentId) {
        List<UserEntity> list = this.baseMapper.getByDepartmentId(departmentId);
        if (CollectionUtil.isEmpty(list)) {
            return false;
        }
        return true;
    }

    public Boolean getByProfessionalId(Long professionalId) {
        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserEntity::getProfessionalId, professionalId)
                .eq(UserEntity::getIsDeleted, 0);
        List<UserEntity> list = this.baseMapper.selectList(queryWrapper);
        if (CollectionUtil.isEmpty(list)) {
            return false;
        }
        return true;
    }

    public Boolean getByPositionId(Long positionId) {
        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserEntity::getPositionId, positionId)
                .eq(UserEntity::getIsDeleted, 0);
        List<UserEntity> list = this.baseMapper.selectList(queryWrapper);
        if (CollectionUtil.isEmpty(list)) {
            return false;
        }
        return true;
    }

    public List<OrganizeMemberPartVo> getUserList(String realName) {
        return this.baseMapper.getUserList(realName);
    }


    public Boolean importExcel(MultipartFile file) {
        try {
            // 读取Excel数据
            List<UserExcel> rows = readExcel(file);
        } catch (Exception e) {
            log.error("导入失败 {}" + e.getMessage());
            throw new CommonException("导入失败");
        }
        return true;
    }

    /**
     * 读取Excel数据
     */
    private List<UserExcel> readExcel(MultipartFile file) throws IOException {
        return EasyExcel.read(file.getInputStream())
                .head(UserExcel.class)
                .sheet()
                .doReadSync();
    }


}
